home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / Borland / Borland C++ V5.02 / BLAZER.PAK / CLIENT.CPP < prev    next >
C/C++ Source or Header  |  1997-05-06  |  11KB  |  442 lines

  1. //----------------------------------------------------------------------------
  2. // ObjectWindows
  3. // Copyright (c) 1995, 1995 by Borland International, All Rights Reserved
  4. //
  5. // Implementation of TClientWindow.
  6. //----------------------------------------------------------------------------
  7. #include <owl/pch.h>
  8. #include <owl/combobox.h>
  9. #include <owl/statusba.h>
  10. #include <owl/celarray.h>
  11. #include <owl/imagelst.h>
  12. #include <owl/mailer.h>
  13. #include <stdio.h>
  14. #include <dos.h>
  15. #include <dir.h>
  16. #include "blazer.h"
  17.  
  18. DEFINE_RESPONSE_TABLE1(TClientWindow, TPaneSplitter)
  19.   EV_TVN_SELCHANGED (TreeWindId,      TvnSelChanged),
  20.   EV_LVN_GETDISPINFO(ListWindId,      LvnGetDispInfo),
  21.   EV_LVN_BEGINLABELEDIT(ListWindId,   LvnBeginLabelEdit),
  22.   EV_LVN_ENDLABELEDIT(ListWindId,     LvnEndLabelEdit),
  23.  
  24.   EV_COMMAND        (DrivesId,         CbnDriveSelected),
  25.   EV_COMMAND        (CM_FILESEND,      CmFileSend),
  26.   EV_COMMAND_ENABLE (CM_FILESEND,      CeFileSend),
  27.   EV_COMMAND        (CM_CONTEXTSELECT, CmContextSelect),
  28.   EV_COMMAND_ENABLE (CM_CONTEXTSELECT, CeContextSelect),
  29. END_RESPONSE_TABLE;
  30.  
  31. DEFINE_HELPCONTEXT(TClientWindow)
  32.   HCENTRY_MENU(IDH_CM_FILESELECT,    CM_FILESELECT),
  33.   HCENTRY_MENU(IDH_CM_FILESEND,      CM_FILESEND),
  34.   HCENTRY_MENU(IDH_CM_EXIT,          CM_EXIT),
  35.   HCENTRY_MENU(IDH_CM_HELPABOUT,     CM_HELPABOUT),
  36.   HCENTRY_MENU(IDH_CM_CONTEXTSELECT, CM_CONTEXTSELECT),
  37.   HCENTRY_CONTROL(IDH_TREEWIND,      TreeWindId),
  38.   HCENTRY_CONTROL(IDH_LISTWIND,      ListWindId),
  39. END_HELPCONTEXT;
  40.  
  41. //
  42. // The main SDI client window that is a TPaneSplitter with two panes:
  43. // On the left is a TTreeWindow to display the directory hierarchy and
  44. // on the right is a TListWindow to display the files within a selected
  45. // directory.
  46. //
  47. TClientWindow::TClientWindow(TWindow* parent)
  48. :
  49.   TPaneSplitter(parent)
  50. {
  51. //  OwnsElements(0);
  52.   Attr.Style |= (WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
  53.   TLayoutMetrics lm;
  54.  
  55.   // Create TreeWindow
  56.   //
  57.   TreeWind = new TPaneTreeWindow(this, TreeWindId, 10, 10, 100, 100);
  58.   TreeWind->Attr.Style   |= WS_VISIBLE | TVS_HASLINES |
  59.                             TVS_HASBUTTONS | TVS_LINESATROOT;
  60.   TreeWind->Attr.ExStyle |= WS_EX_CLIENTEDGE;
  61.  
  62.   // Create ListWindow
  63.   //
  64.   ListWind = new TPaneListWindow(this, ListWindId, 10, 10, 100, 100);
  65.   ListWind->Attr.Style   |= LVS_REPORT | LVS_SORTASCENDING | LVS_EDITLABELS;
  66.   ListWind->Attr.ExStyle |= WS_EX_CLIENTEDGE;
  67.  
  68.   Images = new TImageList(*GetApplication(), IDB_TREEIMAGE,
  69.                           20, 1, TColor(255, 255, 255), IMAGE_BITMAP, 0);
  70. }
  71.  
  72. //
  73. //
  74. //
  75. TClientWindow::~TClientWindow()
  76. {
  77.   delete TreeWind;
  78.   delete ListWind;
  79.   delete Images;
  80. }
  81.  
  82. //
  83. //
  84. //
  85. void
  86. TClientWindow::SetupWindow()
  87. {
  88.   // Initialize base class
  89.   //
  90.   TPaneSplitter::SetupWindow();
  91.   SplitPane(TreeWind, ListWind, psVertical);
  92.  
  93.   // Initialize context sensitive help
  94.   //
  95.   SETUP_HELPCONTEXT(TBlazerApp, TClientWindow);
  96.  
  97.   // Initialize TreeWind
  98.   //
  99.   TreeWind->SetImageList(TTreeWindow::Normal, *Images);
  100.  
  101.   // Initialize ListWind
  102.   //
  103.   TListWindColumn files("Name", 100);
  104.   ListWind->InsertColumn(0, files);
  105.   TListWindColumn date("Modified", 100, TListWindColumn::Left);
  106.   ListWind->InsertColumn(1, date);
  107.   TListWindColumn size("Size", 100, TListWindColumn::Right);
  108.   ListWind->InsertColumn(2, size);
  109. }
  110.  
  111. //
  112. //
  113. //
  114. void
  115. TClientWindow::CleanupWindow()
  116. {
  117.   // Remove context sensitive help info
  118.   //
  119.   CLEANUP_HELPCONTEXT(TBlazerApp, TClientWindow);
  120.  
  121.   // Cleanup the base class
  122.   //
  123.   TPaneSplitter::CleanupWindow();
  124. }
  125.  
  126. //
  127. // A drive was selected in the combobox.
  128. // Read directory information from the drive and store it into
  129. // the TTreeWindow.
  130. //
  131. void
  132. TClientWindow::CbnDriveSelected()
  133. {
  134.   TreeWind->DeleteAllItems();
  135.  
  136.   char drive[10];
  137.   ListOfDrives->GetSelString(drive, sizeof drive);
  138.  
  139.   TTreeItem item(drive, Directory, OpenDirectory);
  140.   TTreeNode driveNode = TreeWind->GetRoot().AddChild(item);
  141.  
  142.   string startDir = drive;
  143.   startDir += "\\*.*";
  144.   AddDirectory(startDir.c_str(), driveNode);
  145.  
  146.   // sort all the children in the tree
  147.   //
  148.   TTreeNode root = TreeWind->GetRoot();
  149.   root.SortChildren(true);
  150.  
  151.   if (::StatusBar)
  152.     ::StatusBar->SetText(" ");
  153.  
  154.   TreeWind->Invalidate();
  155.   ListWind->Invalidate();
  156.  
  157.   TvnSelChanged(TTwNotify());
  158.   root.GetChild().ExpandItem(TTreeNode::Expand);
  159. }
  160.  
  161. //
  162. // Fill TListWindow with files if a directory was selected.
  163. // This function is called when user selects a directory or called
  164. // directory by CbnDriveSelected.
  165. //
  166. void
  167. TClientWindow::TvnSelChanged(TTwNotify far& /*notify*/)
  168. {
  169.   ListWind->DeleteAllItems();
  170.  
  171.   TTreeNode treeItem = TreeWind->GetSelection();
  172.   string fullPath = GetParentDirectory(treeItem);
  173.   if (fullPath.length() == 0)
  174.     return;
  175.  
  176.   // Fill TListWindow with files from selected directory
  177.   //
  178.   fullPath += "*.*";
  179.   ffblk fb;
  180.   bool done = findfirst(fullPath.c_str(), &fb, FA_NORMAL);
  181.   while (!done) {
  182.     TListWindItem item(fb.ff_name, 0);
  183.     ListWind->InsertItem(item);
  184.     done = findnext(&fb);
  185.   }
  186. }
  187.  
  188. //
  189. // Callback notification to handle additional column information
  190. // for each file.
  191. // In this case, display file date timestamp and file size.
  192. //
  193. void
  194. TClientWindow::LvnGetDispInfo(TLwDispInfoNotify& dispInfo)
  195. {
  196.   const int BufLen = 255;
  197.   static char buffer[BufLen];
  198.   TListWindItem& dispInfoItem = *(TListWindItem*)&dispInfo.item;
  199.  
  200.   TListWindItem lvItem(buffer, 0, BufLen);
  201.   lvItem.SetIndex(dispInfoItem.GetIndex());
  202.   ListWind->GetItem(lvItem);
  203.  
  204.   TTreeNode treeItem = TreeWind->GetSelection();
  205.   string parentDir = GetParentDirectory(treeItem);
  206.   parentDir += lvItem.pszText;
  207.  
  208.   // Get information about file
  209.   //
  210.   ffblk fb;
  211.   bool done = findfirst(parentDir.c_str(), &fb, FA_NORMAL);
  212.   if (!done) {
  213.     switch (dispInfoItem.GetSubItem()) {
  214.       case 1: { // date
  215.         struct ff_date_struct  {
  216.           unsigned day : 5;
  217.           unsigned month : 4;
  218.           unsigned year80 : 7;
  219.         };
  220.         ff_date_struct date = *(ff_date_struct*)&fb.ff_fdate;
  221.         sprintf(buffer, "%02d/%02d/%04d", date.month, date.day, date.year80+1980);
  222.         dispInfoItem.SetText(buffer);
  223.         break;
  224.       }
  225.       case 2: { // size
  226.         sprintf(buffer, "%lu", fb.ff_fsize);
  227.         dispInfoItem.SetText(buffer);
  228.         break;
  229.       }
  230.     }
  231.   }
  232. }
  233.  
  234. //
  235. // Recursively traverse the directory hierarchy of the given dirPath.
  236. // dirPath is specified by this format:
  237. //   [drive]:\\{dirs}\\*.*
  238. // where drive is a letter, typically c through z and
  239. //       dirs is zero or more directories separated by a backslash.
  240. //
  241. void
  242. TClientWindow::AddDirectory(const char* dirPath, TTreeNode& parent)
  243. {
  244.   ffblk fb;
  245.   bool done = findfirst(dirPath, &fb, FA_DIREC);
  246.   while (!done) {
  247.     // Allow other programs a chance to work
  248.     //
  249.     // ::Application->PumpWaitingMessages();
  250.     Parent->UpdateWindow();
  251.  
  252.     char* dirName = fb.ff_name;
  253.     if (fb.ff_attrib & FA_DIREC) {
  254.       if (strcmp(dirName, ".") == 0)
  255.         ; // skip
  256.       else if (strcmp(dirName, "..") == 0)
  257.         ; // skip
  258.       else {
  259.         // Add item
  260.         //
  261.         TTreeItem item(dirName, Directory, Directory);
  262.         TTreeNode newParent = parent.AddChild(item);
  263.  
  264.         // Recurse
  265.         //
  266.         TAPointer<char> buffer = new char[strlen(dirPath) + strlen(dirName) + 1 + 1];
  267.         strncpy(buffer, dirPath, strlen(dirPath) - 3);
  268.  
  269.         // Take off *.*
  270.         //
  271.         buffer[strlen(dirPath) - 3] = 0;
  272.  
  273.         if (::StatusBar)
  274.           ::StatusBar->SetText(dirPath);
  275.  
  276.         // Add directory\*.* to end
  277.         //
  278.         strcat(buffer, dirName);
  279.         strcat(buffer, "\\*.*");
  280.         AddDirectory(buffer, newParent);
  281.       }
  282.     }
  283.     done = findnext(&fb);
  284.   }
  285. }
  286.  
  287. //
  288. // Retrieves the directory of the selected item in the TTreeWindow.
  289. //
  290. string
  291. TClientWindow::GetParentDirectory(TTreeNode& treeNode)
  292. {
  293.   string path = "";
  294.   while (treeNode != 0) {
  295.     string toBeAdded = path;
  296.     const int bufLen = 255;
  297.     char* buffer = new char[bufLen];
  298.     buffer[0] = 0;
  299.  
  300.     TTreeItem tvItem(buffer, bufLen);
  301.     treeNode.GetItem(&tvItem);
  302.  
  303.     path = buffer;
  304.     path += "\\";
  305.     path += toBeAdded;
  306.     treeNode = treeNode.GetParent();
  307.     delete[] buffer;
  308.   }
  309.   string fullPath = path;
  310.   return fullPath;
  311. }
  312.  
  313. //
  314. // Notification to begin label editing.
  315. //
  316. bool
  317. TClientWindow::LvnBeginLabelEdit(TLwDispInfoNotify&)
  318. {
  319.   ::MessageBeep(-1);
  320.   return false;
  321. }
  322.  
  323. //
  324. // Notification to end label editing.
  325. //
  326. void
  327. TClientWindow::LvnEndLabelEdit(TLwDispInfoNotify& dispInfo)
  328. {
  329.   if (dispInfo.item.iItem != -1) {
  330.     if (dispInfo.item.pszText) {
  331.       char text[512];
  332.       sprintf(text, "Attempting to rename to %s on item number %d\n",
  333.         dispInfo.item.pszText, dispInfo.item.iItem);
  334.       MessageBox(text, "Message");
  335.     }
  336.   }
  337. }
  338.  
  339. //
  340. // Determines if files are selected in the TListWindow.
  341. //
  342. bool
  343. TClientWindow::AreFilesSelected()
  344. {
  345.   if (ListWind) {
  346.     int count = ListWind->GetItemCount();
  347.     for (int i = 0; i < count; i++)
  348.       if (ListWind->GetItemState(i, LVIS_SELECTED))
  349.         return true;
  350.   }
  351.   return false;
  352. }
  353.  
  354. //
  355. //
  356. //
  357. void
  358. TClientWindow::CeFileSend(TCommandEnabler& ce)
  359. {
  360.   ce.Enable(AreFilesSelected());
  361. }
  362.  
  363. //
  364. // Send selected files via MAPI.
  365. //
  366. void
  367. TClientWindow::CmFileSend()
  368. {
  369.   if (ListWind) {
  370.     int count = ListWind->GetItemCount();
  371.     TTreeNode treeItem = TreeWind->GetSelection();
  372.     string path = GetParentDirectory(treeItem);
  373.     if (path.length() == 0)
  374.       return;
  375.     for (int i = 0; i < count; i++) {
  376.       const int length = 1024;
  377.       char* fileName = new char[length];
  378.       TListWindItem item(fileName, 0, length);
  379.       item.SetIndex(i);
  380.       ListWind->GetItem(item);
  381.       if (ListWind->GetItemState(i, LVIS_SELECTED)) {
  382.         string temp = path + fileName;
  383.         ::Application->SaveMenuChoice(temp.c_str());
  384.         ::Application->GetMailer()->SendDocuments(this, temp.c_str(), fileName);
  385.       }
  386.       delete[] fileName;
  387.     }
  388.   }
  389. }
  390.  
  391. //
  392. //
  393. //
  394. void
  395. TClientWindow::CeContextSelect(TCommandEnabler& ce)
  396. {
  397.   ce.Enable(AreFilesSelected());
  398. }
  399.  
  400. //
  401. // Add selected files to the Most-Recently-Used list.
  402. //
  403. void
  404. TClientWindow::CmContextSelect()
  405. {
  406.   if (ListWind) {
  407.     int count = ListWind->GetItemCount();
  408.     TTreeNode treeItem = TreeWind->GetSelection();
  409.     string path = GetParentDirectory(treeItem);
  410.     if (path.length() == 0)
  411.       return;
  412.     for (int i = 0; i < count; i++) {
  413.       const int length = 1024;
  414.       char* fileName = new char[length];
  415.       TListWindItem item(fileName, 0, length);
  416.       item.SetIndex(i);
  417.       ListWind->GetItem(item);
  418.       if (ListWind->GetItemState(i, LVIS_SELECTED)) {
  419.         string temp = path + fileName;
  420.         ::Application->SaveMenuChoice(temp.c_str());
  421.       }
  422.       delete[] fileName;
  423.     }
  424.   }
  425. }
  426.  
  427. //----------------------------------------------------------------------------
  428.  
  429. DEFINE_RESPONSE_TABLE1(TComboBoxAsGadget, TComboBox)
  430.   EV_NOTIFY_AT_CHILD(CBN_SELCHANGE, CbnSelChanged),
  431. END_RESPONSE_TABLE;
  432.  
  433. //
  434. //
  435. //
  436. void
  437. TComboBoxAsGadget::CbnSelChanged()
  438. {
  439.   GetParentO()->SendNotification(GetId(), 0, 0);
  440. }
  441.  
  442.